#!/usr/bin/env python

from google.appengine.dist import use_library
use_library('django', '1.2')

import logging
import os
import random
import tasks
from datetime import datetime
from django.utils import simplejson as json
from google.appengine.ext import db
from google.appengine.ext import deferred
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp import util

from models import *

BATCH_SIZE = 30

def get_task(key=None):
  """Returns a task with open items"""
  if key:
    task = db.get(key)
    if task and task.todo: return task
  task = None
  i = 0
  while i < 10 and not task:
    tasks = Task.all().filter('todo !=', None).fetch(1)
    i += 1
    if tasks:
      task = tasks[0]
      task.random = random.random()
      task.put()
      if not task.todo: continue
      return task
  return None

class ServeWorkerHandler(webapp.RequestHandler):
  def get(self):
    task = get_task()
    if not task:
      self.error(404)
      return
    num = min(len(task.todo), BATCH_SIZE)
    item_keys = random.sample(task.todo, num)
    items = db.get(item_keys)

    user = None
    if users.get_current_user() is not None:
      user = AppUser.get_for_current_user().key().id_or_name()

    self.response.headers['Content-type'] = 'text/javascript'
    path = os.path.join(os.path.dirname(__file__),
                        'templates/worker.js.tmpl')
    self.response.out.write(template.render(path, {
      'task': task,
      'items': items,
      'user': user
    }))

class AcceptAnswerHandler(webapp.RequestHandler):
  def post(self):
    tasks.accept_answer(self.request.body)
#    deferred.defer(tasks.accept_answer, self.request.body)

    data = json.loads(self.request.body)
    task = db.get(data['taskKey'])

    # Get the next set of inputs
    next_item_key = None
    if not task.todo:
      self.error(404)
      return
    num = min(len(task.todo), BATCH_SIZE)
    next_item_keys = random.sample(task.todo, num)
    next_items = db.get(next_item_keys)
    obj = {
      'taskKey': str(task.key()),
      'items': []
    }
    for item in next_items:
      obj['items'].append({
        'itemKey': str(item.key()),
        'prompt': item.prompt
      })
    self.response.out.write(json.dumps(obj))

class MainHandler(webapp.RequestHandler):
  def get(self):
    user = None
    loginout_url = users.create_login_url('/')
    if users.get_current_user() is not None:
      user = AppUser.get_for_current_user()
      loginout_url = users.create_logout_url('/')
    path = os.path.join(os.path.dirname(__file__),
                        'templates/main.html.tmpl')
    self.response.out.write(template.render(path, {
      'user': user,
      'loginout_url': loginout_url
    }))

class NewTaskHandler(webapp.RequestHandler):
  @util.login_required
  def get(self):
    if not users.is_current_user_admin():
      self.redirect(users.create_login_url('/new'))
      return
    path = os.path.join(os.path.dirname(__file__),
                        'templates/new.html.tmpl')
    self.response.out.write(template.render(path, {}))

  def post(self):
    inputs_str = self.request.get('inputs')
    script = self.request.get('script')
    deferred.defer(tasks.new_task, inputs_str=inputs_str,
                   script=script, _countdown=1)
    self.redirect('/')

class AdminListHandler(webapp.RequestHandler):
  @util.login_required
  def get(self):
    if not users.is_current_user_admin():
      self.redirect(users.create_login_url('/new'))
      return
    tasks = Task.all().fetch(100)
    path = os.path.join(os.path.dirname(__file__),
                        'templates/admin.list.html.tmpl')
    self.response.out.write(template.render(path, {
      'tasks': tasks,
    }))

class AdminHandler(webapp.RequestHandler):
  def get(self, task_key):
    task = db.get(str(task_key))
    items = db.get(task.done)
    path = os.path.join(os.path.dirname(__file__),
                        'templates/admin.task.html.tmpl')
    self.response.out.write(template.render(path, {
      'task': task,
      'items': items,
      'pct': len(task.done) * 100.0 / (len(task.todo) + len(task.done))
    }))

MAP = [('/', MainHandler),
  ('/serve', ServeWorkerHandler),
  ('/answer', AcceptAnswerHandler),
  ('/new', NewTaskHandler),
  ('/admin', AdminListHandler),
  ('/admin/(.+)', AdminHandler)]

def main():
  util.run_wsgi_app(webapp.WSGIApplication(MAP, debug=True))

if __name__ == '__main__':
  main()
